package com.hyou.springboot.handler.exception;

import java.io.Serializable;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.hyou.springboot.base.ResponseMessage;
import com.hyou.springboot.util.ResponseMessageUtil;

/**
 * <pre>
 * 统一异常处理
 * 在业务模块层、负载均衡层等出现Conroller的模块中，可以通过@ControllerAdvice的方式实现异常的统一处理。
 * </pre>
 * 
 * @author FengChangshuo
 * @version 1.0.0 2018-03-27 17:27:23 初始创建
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    /**
     * <pre>
     * 统一异常拦截处理。采用前后端分离的思路，后台全部提供Ajax访问接口。
     * 该方法拦截异常后统一以JSON格式进行应答。
     * 
     * 应答消息格式示例：
     * {
     *     "code" : 100,
     *     "msg" : "请求的服务或资源不存在",
     *     "data" : null
     * }
     * 
     * 或：
     * {
     *     "code" : 1,
     *     "msg" : "${errMsg}",
     *     "data" : null
     * }
     * 
     * 版本修改历史记录：
     * 1) 1.0.0 2018-03-27 17:28:19 FengChangshuo 初始创建
     * </pre>
     * 
     * @param request HttpServletRequest
     * @param e Exception
     * @return 应答消息
     */
    @ExceptionHandler
    @ResponseBody
    public ResponseMessage<Serializable> exception(HttpServletRequest request, Exception e) {
        
        if (e instanceof NoHandlerFoundException) {
            return ResponseMessageUtil.genResourceNotFoundResult();
        }
        
        // Request method 'xxx' not supported
        if (e instanceof HttpRequestMethodNotSupportedException) {
            return ResponseMessageUtil.genFailResult(e.getMessage());
        }
        
        // Required request body is missing
        if (e instanceof HttpMessageNotReadableException) {
            return ResponseMessageUtil.genFailResult("请求缺失消息体");
        }
        
        log.error("请求异常：servletpath = {}", request.getServletPath());
        log.error(e.getMessage(), e);
        return ResponseMessageUtil.genFailResult(e.getMessage());
    }
    
}
